package ca.cbc.giscommon.dao;

import java.util.Formatter;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.vividsolutions.jts.geom.Geometry;

import ca.cbc.giscommon.entity.Shape;
import ca.cbc.giscommon.util.GeometryUtil;
import ca.cbc.giscommon.util.StringUtil;

public class ShapeDAO extends EntityHome<Shape>{

	private ZoneDAO zoneDAO = new ZoneDAO();
	
	public void saveOrUpdate(Shape shape) {
		this.setZoneIfExist(shape);
		super.saveOrUpdate(shape);
    }
	
	private void setZoneIfExist(Shape shape) {
		Geometry geo = shape.getTheGeom();
		if(geo != null) {
			shape.setZones(zoneDAO.getZones(geo));
		}
	}
	
	public void save(Shape shape) {
		this.setZoneIfExist(shape);
		super.save(shape);
    }
	
	@Override
	public String getFullClassName() {
		return Shape.class.getCanonicalName();
	}
	
	@SuppressWarnings("unchecked")
	public List<Shape> list(String zoneIds, Geometry bbox, String shapeTypeIds, String categoryIds, String orderBy, boolean isAscending, int limit, int offset) {
    	Criteria criteria = getCurrentSession().createCriteria(Shape.class);
    	
    	if(!StringUtil.instance.isNullOrEmpty(orderBy)) {
	    	if(isAscending) {
	    		criteria.addOrder(Order.asc(orderBy));
	    	} else {
	    		criteria.addOrder(Order.desc(orderBy));
	    	}
    	}
    	
    	if(!StringUtil.instance.isNullOrEmpty(zoneIds)) {   		
    		criteria.createCriteria("zones").add(Restrictions.in("id", StringUtil.instance.parseIds(zoneIds)));
    	} else if (bbox != null) {
    		String query = new Formatter().format("ST_Intersects(ST_GeomFromText('%s', %d), this_.the_geom)", bbox.toString(), GeometryUtil.instance.getSRID()).toString();
    		criteria.add(Restrictions.sqlRestriction(query));
    	}
    	
    	if(!StringUtil.instance.isNullOrEmpty(shapeTypeIds)) {   		
    		criteria.createCriteria("shapeType").add(Restrictions.in("id", StringUtil.instance.parseIds(shapeTypeIds)));
    	}

    	if(!StringUtil.instance.isNullOrEmpty(categoryIds)) {   		
    		criteria.createCriteria("shapeType").createCriteria("category").add(Restrictions.in("id", StringUtil.instance.parseIds(categoryIds)));
    	}
    	
    	if(limit > 0) {
    		criteria.setMaxResults(limit);
    	}
    	
    	if(offset > 0) {
    		criteria.setFirstResult(offset);
    	}
    	
    	return criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
    }
}
